package org.microframework.cloud.logs.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.microframework.cloud.logs.model.domain.ApiLog;
import org.microframework.cloud.logs.model.domain.LoginLog;
import org.microframework.cloud.logs.model.domain.OperationLog;
import org.microframework.cloud.logs.model.domain.SystemLog;
import org.microframework.cloud.logs.model.dto.StatisticsDTO;
import org.microframework.cloud.logs.model.dto.StatisticsDTO.DailyStats;
import org.microframework.cloud.logs.model.dto.StatisticsDTO.TrendData;
import org.microframework.cloud.logs.service.StatisticsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

/**
 * 日志统计服务实现类
 *
 * @author zs
 * @version 1.0.0
 * @since 2024-06-14
 */
@Service
public class StatisticsServiceImpl implements StatisticsService {

    private static final Logger log = LoggerFactory.getLogger(StatisticsServiceImpl.class);

    @Override
    public StatisticsDTO getLoginStatistics(Integer days) {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(days);
            
            // 查询总记录数
            String totalSql = "SELECT COUNT(*) as total FROM " + LoginLog.TABLE_NAME;
            Record totalRecord = Db.findFirst(totalSql);
            dto.setTotalCount(totalRecord.getLong("total"));
            
            // 查询成功记录数
            String successSql = "SELECT COUNT(*) as success FROM " + LoginLog.TABLE_NAME + " WHERE status = 0";
            Record successRecord = Db.findFirst(successSql);
            dto.setSuccessCount(successRecord.getLong("success"));
            
            // 查询失败记录数
            String failureSql = "SELECT COUNT(*) as failure FROM " + LoginLog.TABLE_NAME + " WHERE status = 1";
            Record failureRecord = Db.findFirst(failureSql);
            dto.setFailureCount(failureRecord.getLong("failure"));
            
            // 查询每日统计
            String dailySql = "SELECT DATE(login_time) as date, COUNT(*) as count FROM " + LoginLog.TABLE_NAME 
                    + " WHERE login_time >= ? GROUP BY DATE(login_time) ORDER BY date";
            List<Record> dailyRecords = Db.find(dailySql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : dailyRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            // 查询浏览器分布
            String browserSql = "SELECT browser, COUNT(*) as count FROM " + LoginLog.TABLE_NAME 
                    + " GROUP BY browser";
            List<Record> browserRecords = Db.find(browserSql);
            Map<String, Long> browserStats = new HashMap<>();
            for (Record record : browserRecords) {
                browserStats.put(record.getStr("browser"), record.getLong("count"));
            }
            dto.setCategoryStats(browserStats);
            
            // 查询趋势数据
            String trendSql = "SELECT DATE_FORMAT(login_time, '%Y-%m-%d %H:00:00') as time_point, COUNT(*) as count FROM " 
                    + LoginLog.TABLE_NAME + " WHERE login_time >= ? GROUP BY time_point ORDER BY time_point";
            List<Record> trendRecords = Db.find(trendSql, startDate);
            List<TrendData> trendData = new ArrayList<>();
            for (Record record : trendRecords) {
                TrendData data = new TrendData();
                data.setTimePoint(record.getStr("time_point"));
                data.setCount(record.getLong("count"));
                trendData.add(data);
            }
            dto.setTrendData(trendData);
            
            return dto;
        } catch (Exception e) {
            log.error("获取登录统计数据异常", e);
            return new StatisticsDTO();
        }
    }

    @Override
    public StatisticsDTO getOperationStatistics(Integer days) {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(days);
            
            // 查询总记录数
            String totalSql = "SELECT COUNT(*) as total FROM " + OperationLog.TABLE_NAME;
            Record totalRecord = Db.findFirst(totalSql);
            dto.setTotalCount(totalRecord.getLong("total"));
            
            // 查询成功记录数
            String successSql = "SELECT COUNT(*) as success FROM " + OperationLog.TABLE_NAME + " WHERE status = 0";
            Record successRecord = Db.findFirst(successSql);
            dto.setSuccessCount(successRecord.getLong("success"));
            
            // 查询失败记录数
            String failureSql = "SELECT COUNT(*) as failure FROM " + OperationLog.TABLE_NAME + " WHERE status = 1";
            Record failureRecord = Db.findFirst(failureSql);
            dto.setFailureCount(failureRecord.getLong("failure"));
            
            // 查询每日统计
            String dailySql = "SELECT DATE(oper_time) as date, COUNT(*) as count FROM " + OperationLog.TABLE_NAME 
                    + " WHERE oper_time >= ? GROUP BY DATE(oper_time) ORDER BY date";
            List<Record> dailyRecords = Db.find(dailySql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : dailyRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            // 查询操作类型分布
            String typeSql = "SELECT oper_type, COUNT(*) as count FROM " + OperationLog.TABLE_NAME 
                    + " GROUP BY oper_type";
            List<Record> typeRecords = Db.find(typeSql);
            Map<String, Long> typeStats = new HashMap<>();
            for (Record record : typeRecords) {
                typeStats.put(record.getStr("oper_type"), record.getLong("count"));
            }
            dto.setCategoryStats(typeStats);
            
            // 查询趋势数据
            String trendSql = "SELECT DATE_FORMAT(oper_time, '%Y-%m-%d %H:00:00') as time_point, COUNT(*) as count FROM " 
                    + OperationLog.TABLE_NAME + " WHERE oper_time >= ? GROUP BY time_point ORDER BY time_point";
            List<Record> trendRecords = Db.find(trendSql, startDate);
            List<TrendData> trendData = new ArrayList<>();
            for (Record record : trendRecords) {
                TrendData data = new TrendData();
                data.setTimePoint(record.getStr("time_point"));
                data.setCount(record.getLong("count"));
                trendData.add(data);
            }
            dto.setTrendData(trendData);
            
            return dto;
        } catch (Exception e) {
            log.error("获取操作日志统计数据异常", e);
            return new StatisticsDTO();
        }
    }

    @Override
    public StatisticsDTO getSystemStatistics(Integer days) {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(days);
            
            // 查询总记录数
            String totalSql = "SELECT COUNT(*) as total FROM " + SystemLog.TABLE_NAME;
            Record totalRecord = Db.findFirst(totalSql);
            dto.setTotalCount(totalRecord.getLong("total"));
            
            // 查询成功记录数
            String successSql = "SELECT COUNT(*) as success FROM " + SystemLog.TABLE_NAME + " WHERE status = 0";
            Record successRecord = Db.findFirst(successSql);
            dto.setSuccessCount(successRecord.getLong("success"));
            
            // 查询失败记录数
            String failureSql = "SELECT COUNT(*) as failure FROM " + SystemLog.TABLE_NAME + " WHERE status = 1";
            Record failureRecord = Db.findFirst(failureSql);
            dto.setFailureCount(failureRecord.getLong("failure"));
            
            // 查询每日统计
            String dailySql = "SELECT DATE(create_time) as date, COUNT(*) as count FROM " + SystemLog.TABLE_NAME 
                    + " WHERE create_time >= ? GROUP BY DATE(create_time) ORDER BY date";
            List<Record> dailyRecords = Db.find(dailySql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : dailyRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            // 查询日志级别分布
            String levelSql = "SELECT level, COUNT(*) as count FROM " + SystemLog.TABLE_NAME 
                    + " GROUP BY level";
            List<Record> levelRecords = Db.find(levelSql);
            Map<String, Long> levelStats = new HashMap<>();
            for (Record record : levelRecords) {
                levelStats.put(record.getStr("level"), record.getLong("count"));
            }
            dto.setCategoryStats(levelStats);
            
            // 查询趋势数据
            String trendSql = "SELECT DATE_FORMAT(create_time, '%Y-%m-%d %H:00:00') as time_point, COUNT(*) as count FROM " 
                    + SystemLog.TABLE_NAME + " WHERE create_time >= ? GROUP BY time_point ORDER BY time_point";
            List<Record> trendRecords = Db.find(trendSql, startDate);
            List<TrendData> trendData = new ArrayList<>();
            for (Record record : trendRecords) {
                TrendData data = new TrendData();
                data.setTimePoint(record.getStr("time_point"));
                data.setCount(record.getLong("count"));
                trendData.add(data);
            }
            dto.setTrendData(trendData);
            
            return dto;
        } catch (Exception e) {
            log.error("获取系统日志统计数据异常", e);
            return new StatisticsDTO();
        }
    }

    @Override
    public StatisticsDTO getApiStatistics(Integer days) {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(days);
            
            // 查询总记录数
            String totalSql = "SELECT COUNT(*) as total FROM " + ApiLog.TABLE_NAME;
            Record totalRecord = Db.findFirst(totalSql);
            dto.setTotalCount(totalRecord.getLong("total"));
            
            // 查询成功记录数
            String successSql = "SELECT COUNT(*) as success FROM " + ApiLog.TABLE_NAME + " WHERE status = 0";
            Record successRecord = Db.findFirst(successSql);
            dto.setSuccessCount(successRecord.getLong("success"));
            
            // 查询失败记录数
            String failureSql = "SELECT COUNT(*) as failure FROM " + ApiLog.TABLE_NAME + " WHERE status = 1";
            Record failureRecord = Db.findFirst(failureSql);
            dto.setFailureCount(failureRecord.getLong("failure"));
            
            // 查询每日统计
            String dailySql = "SELECT DATE(call_time) as date, COUNT(*) as count FROM " + ApiLog.TABLE_NAME 
                    + " WHERE call_time >= ? GROUP BY DATE(call_time) ORDER BY date";
            List<Record> dailyRecords = Db.find(dailySql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : dailyRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            // 查询服务分布
            String serviceSql = "SELECT service_name, COUNT(*) as count FROM " + ApiLog.TABLE_NAME 
                    + " GROUP BY service_name";
            List<Record> serviceRecords = Db.find(serviceSql);
            Map<String, Long> serviceStats = new HashMap<>();
            for (Record record : serviceRecords) {
                serviceStats.put(record.getStr("service_name"), record.getLong("count"));
            }
            dto.setCategoryStats(serviceStats);
            
            // 查询趋势数据
            String trendSql = "SELECT DATE_FORMAT(call_time, '%Y-%m-%d %H:00:00') as time_point, COUNT(*) as count FROM " 
                    + ApiLog.TABLE_NAME + " WHERE call_time >= ? GROUP BY time_point ORDER BY time_point";
            List<Record> trendRecords = Db.find(trendSql, startDate);
            List<TrendData> trendData = new ArrayList<>();
            for (Record record : trendRecords) {
                TrendData data = new TrendData();
                data.setTimePoint(record.getStr("time_point"));
                data.setCount(record.getLong("count"));
                trendData.add(data);
            }
            dto.setTrendData(trendData);
            
            return dto;
        } catch (Exception e) {
            log.error("获取API调用统计数据异常", e);
            return new StatisticsDTO();
        }
    }

    @Override
    public StatisticsDTO getErrorStatistics(Integer days) {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(days);
            
            // 查询总记录数
            String totalSql = "SELECT COUNT(*) as total FROM " + SystemLog.TABLE_NAME + " WHERE level = 'ERROR'";
            Record totalRecord = Db.findFirst(totalSql);
            dto.setTotalCount(totalRecord.getLong("total"));
            
            // 查询每日统计
            String dailySql = "SELECT DATE(create_time) as date, COUNT(*) as count FROM " + SystemLog.TABLE_NAME 
                    + " WHERE level = 'ERROR' AND create_time >= ? GROUP BY DATE(create_time) ORDER BY date";
            List<Record> dailyRecords = Db.find(dailySql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : dailyRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            // 查询错误类型分布
            String typeSql = "SELECT error_type, COUNT(*) as count FROM " + SystemLog.TABLE_NAME 
                    + " WHERE level = 'ERROR' GROUP BY error_type";
            List<Record> typeRecords = Db.find(typeSql);
            Map<String, Long> typeStats = new HashMap<>();
            for (Record record : typeRecords) {
                typeStats.put(record.getStr("error_type"), record.getLong("count"));
            }
            dto.setCategoryStats(typeStats);
            
            // 查询趋势数据
            String trendSql = "SELECT DATE_FORMAT(create_time, '%Y-%m-%d %H:00:00') as time_point, COUNT(*) as count FROM " 
                    + SystemLog.TABLE_NAME + " WHERE level = 'ERROR' AND create_time >= ? GROUP BY time_point ORDER BY time_point";
            List<Record> trendRecords = Db.find(trendSql, startDate);
            List<TrendData> trendData = new ArrayList<>();
            for (Record record : trendRecords) {
                TrendData data = new TrendData();
                data.setTimePoint(record.getStr("time_point"));
                data.setCount(record.getLong("count"));
                trendData.add(data);
            }
            dto.setTrendData(trendData);
            
            return dto;
        } catch (Exception e) {
            log.error("获取错误日志统计数据异常", e);
            return new StatisticsDTO();
        }
    }

    @Override
    public StatisticsDTO getDashboardData() {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(7); // 默认统计最近7天
            
            // 查询登录统计
            String loginSql = "SELECT COUNT(*) as total, SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) as success, " +
                    "SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as failure FROM " + LoginLog.TABLE_NAME +
                    " WHERE login_time >= ?";
            Record loginRecord = Db.findFirst(loginSql, startDate);
            dto.setTotalCount(loginRecord.getLong("total"));
            dto.setSuccessCount(loginRecord.getLong("success"));
            dto.setFailureCount(loginRecord.getLong("failure"));
            
            // 查询操作统计
            String operSql = "SELECT COUNT(*) as total FROM " + OperationLog.TABLE_NAME +
                    " WHERE oper_time >= ?";
            Record operRecord = Db.findFirst(operSql, startDate);
            Map<String, Long> categoryStats = new HashMap<>();
            categoryStats.put("操作日志", operRecord.getLong("total"));
            
            // 查询系统日志统计
            String sysSql = "SELECT COUNT(*) as total FROM " + SystemLog.TABLE_NAME +
                    " WHERE create_time >= ?";
            Record sysRecord = Db.findFirst(sysSql, startDate);
            categoryStats.put("系统日志", sysRecord.getLong("total"));
            
            // 查询API调用统计
            String apiSql = "SELECT COUNT(*) as total FROM " + ApiLog.TABLE_NAME +
                    " WHERE call_time >= ?";
            Record apiRecord = Db.findFirst(apiSql, startDate);
            categoryStats.put("API调用", apiRecord.getLong("total"));
            
            dto.setCategoryStats(categoryStats);
            
            // 查询每日趋势
            String trendSql = "SELECT DATE(login_time) as date, COUNT(*) as count FROM " + LoginLog.TABLE_NAME +
                    " WHERE login_time >= ? GROUP BY DATE(login_time) ORDER BY date";
            List<Record> trendRecords = Db.find(trendSql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : trendRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            return dto;
        } catch (Exception e) {
            log.error("获取综合统计看板数据异常", e);
            return new StatisticsDTO();
        }
    }

    @Override
    public StatisticsDTO getUserActivityData(Integer days) {
        try {
            StatisticsDTO dto = new StatisticsDTO();
            Date startDate = getStartDate(days);
            
            // 查询用户活跃度统计
            String activitySql = "SELECT username, COUNT(*) as count FROM " + LoginLog.TABLE_NAME +
                    " WHERE login_time >= ? GROUP BY username ORDER BY count DESC LIMIT 10";
            List<Record> activityRecords = Db.find(activitySql, startDate);
            Map<String, Long> activityStats = new HashMap<>();
            for (Record record : activityRecords) {
                activityStats.put(record.getStr("username"), record.getLong("count"));
            }
            dto.setCategoryStats(activityStats);
            
            // 查询每日活跃度
            String dailySql = "SELECT DATE(login_time) as date, COUNT(DISTINCT username) as count FROM " + LoginLog.TABLE_NAME +
                    " WHERE login_time >= ? GROUP BY DATE(login_time) ORDER BY date";
            List<Record> dailyRecords = Db.find(dailySql, startDate);
            List<DailyStats> dailyStats = new ArrayList<>();
            for (Record record : dailyRecords) {
                DailyStats stats = new DailyStats();
                stats.setDate(record.getStr("date"));
                stats.setCount(record.getLong("count"));
                dailyStats.add(stats);
            }
            dto.setDailyStats(dailyStats);
            
            // 查询时段分布
            String timeSql = "SELECT HOUR(login_time) as hour, COUNT(*) as count FROM " + LoginLog.TABLE_NAME +
                    " WHERE login_time >= ? GROUP BY HOUR(login_time) ORDER BY hour";
            List<Record> timeRecords = Db.find(timeSql, startDate);
            List<TrendData> trendData = new ArrayList<>();
            for (Record record : timeRecords) {
                TrendData data = new TrendData();
                data.setTimePoint(String.format("%02d:00", record.getInt("hour")));
                data.setCount(record.getLong("count"));
                trendData.add(data);
            }
            dto.setTrendData(trendData);
            
            return dto;
        } catch (Exception e) {
            log.error("获取用户活跃度分析数据异常", e);
            return new StatisticsDTO();
        }
    }

    /**
     * 获取开始日期
     */
    private Date getStartDate(Integer days) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -days);
        return calendar.getTime();
    }
} 